﻿using System;
using System.Collections.Generic;
using OpenCompiler.LanguageElements;
using OpenCompiler.Scanning;

namespace OpenCompiler
{
	public class Keywords
	{
		public static readonly Dictionary<Keyword, ILanguageElement> Elements = new Dictionary<Keyword, ILanguageElement>();
		private static readonly Dictionary<string, bool> _validKeywords;

		static Keywords()
		{
			_validKeywords = new Dictionary<string, bool>();
			var names = Enum.GetNames(typeof(Keyword));
			foreach (var name in names)
			{
				_validKeywords[name.ToLower()] = true;
			}

			Elements[Keyword.CLASS] = new Class();
			Elements[Keyword.EVENT] = new Event();
			Elements[Keyword.INTERFACE] = new Interface();
			Elements[Keyword.NAMESPACE] = new Namespace();
			Elements[Keyword.STRUCT] = new Struct();
			Elements[Keyword.USING] = new Using();

			// Modifiers
			var modifierElement = new Modifier();
			Elements[Keyword.PUBLIC] = modifierElement;
			Elements[Keyword.PRIVATE] = modifierElement;
			Elements[Keyword.PROTECTED] = modifierElement;
			Elements[Keyword.ABSTRACT] = modifierElement;
			Elements[Keyword.VIRTUAL] = modifierElement;
			Elements[Keyword.INTERNAL] = modifierElement;
			Elements[Keyword.STATIC] = modifierElement;
			Elements[Keyword.READONLY] = modifierElement;
			Elements[Keyword.VOLATILE] = modifierElement;
			Elements[Keyword.UNSAFE] = modifierElement;
			Elements[Keyword.PARTIAL] = modifierElement;
			Elements[Keyword.SEALED] = modifierElement;
			Elements[Keyword.OVERRIDE] = modifierElement;

			// Built in types
			var builtInTypesElement = new BuiltInTypes();
			Elements[Keyword.BOOL] = builtInTypesElement;
			Elements[Keyword.SBYTE] = builtInTypesElement;
			Elements[Keyword.BYTE] = builtInTypesElement;
			Elements[Keyword.CHAR] = builtInTypesElement;
			Elements[Keyword.INT] = builtInTypesElement;
			Elements[Keyword.UINT] = builtInTypesElement;
			Elements[Keyword.SHORT] = builtInTypesElement;
			Elements[Keyword.USHORT] = builtInTypesElement;
			Elements[Keyword.LONG] = builtInTypesElement;
			Elements[Keyword.ULONG] = builtInTypesElement;
			Elements[Keyword.FLOAT] = builtInTypesElement;
			Elements[Keyword.DOUBLE] = builtInTypesElement;
			Elements[Keyword.DECIMAL] = builtInTypesElement;
			Elements[Keyword.STRING] = builtInTypesElement;
			Elements[Keyword.OBJECT] = builtInTypesElement;
		}


		public static bool IsKeywordValid(string token)
		{
			if (_validKeywords.ContainsKey(token))
			{
				var keyword = GetKeywordFromToken(token);
				if (Elements.ContainsKey(keyword))
				{
					return true;
				}
			}

			return false;
		}

		public static Keyword GetKeywordFromToken(string token)
		{
			var keyword = (Keyword)Enum.Parse(typeof(Keyword), token.ToUpperInvariant());
			return keyword;
		}

		public static ILanguageElement GetLanguageElementFromKeyword(Keyword keyword)
		{
			return Elements[keyword];
		}

		public static ILanguageElement GetLanguageElementFromToken(string token)
		{
			var keyword = GetKeywordFromToken(token);
			return Elements[keyword];
		}
	}
}
